#ifndef UNTITLED_BISEARCH_H
#define UNTITLED_BISEARCH_H
#include "graph.h"
#include "trans.h"

struct Compare1 {
    bool operator()(const std::tuple<int, time_t, int>& a, const std::tuple<int, time_t, int>& b) const {
        // 按第一位升序比较
        if (std::get<0>(a) != std::get<0>(b)) {
            return std::get<0>(a) > std::get<0>(b); // 升序，所以返回 a > b 时放入优先队列
        }

        // 按第二位降序比较
        if (std::get<1>(a) != std::get<1>(b)) {
            return std::get<1>(a) < std::get<1>(b); // 降序，所以返回 a < b 时放入优先队列
        }

        // 按第三位升序比较
        if (std::get<2>(a) != std::get<2>(b)) {
            return std::get<2>(a) > std::get<2>(b); // 升序
        }

        return false;
    }
};

class bTrans {
public:
    bTrans(std::string filename);
    int n = 0, m = 0;
    std::unordered_map<int, tEdge> edges;
    std::unordered_map<std::tuple<int, time_t, inout>, std::unordered_set<int>, tuple_hash> in, out;
    std::unordered_map<std::tuple<int, time_t, inout>, int, tuple_hash> dis1, dis2;
    std::priority_queue<std::tuple<int, time_t, inout, int>, std::vector<std::tuple<int, time_t, inout, int>>, std::greater<>> pq1, pq2;
    std::unordered_map<int, std::set<time_t>> intimes, outtimes;
    std::unordered_map<int, int> f;
    int bisearch(int source, int target, time_t start, time_t end);
    void search1(int source, int target, time_t start, time_t end);
    void search2(int source, time_t start, time_t end);
};

class bDij {
public:
    bDij(std::string filename);
    int n = 0, m = 0;
    std::unordered_map<int, Edge> edges;
    std::unordered_map<int, std::set<Edge, EdgeOrderByOutTime>> out;
    std::unordered_map<int, std::set<Edge, EdgeOrderByInTime>> in;
    std::unordered_map<int, std::map<time_t, int>> dis1, dis2;
    std::priority_queue<std::tuple<int, time_t, int>, std::vector<std::tuple<int, time_t, int>>, std::greater<>> pq1;
    std::priority_queue<std::tuple<int, time_t, int>, std::vector<std::tuple<int, time_t, int>>, Compare1> pq2;
    std::unordered_map<int, int> f;
    int bisearch(int source, int target, time_t start, time_t end);
    void search1(int source, int target, time_t start, time_t end);
    void search2(int source, time_t start, time_t end);
};

class bfDij {
public:
    bfDij(std::string filename);
    int n = 0, m = 0;
    std::unordered_map<int, Edge> edges;
    std::unordered_map<int, std::set<Edge, EdgeOrderByOutTime>> out;
    std::unordered_map<int, std::set<Edge, EdgeOrderByInTime>> in;
    std::unordered_map<int, int> dis1, dis2;
    std::priority_queue<std::tuple<time_t, int>, std::vector<std::tuple<time_t, int>>, std::greater<>> pq1;
    std::priority_queue<std::tuple<time_t, int>> pq2;
    std::unordered_map<int, int> f;
    int bisearch(int source, int target, time_t start, time_t end);
    void search1(int source, int target, time_t start, time_t end);
};

class bfTrans {
public:
    bfTrans(std::string filename);
    int n = 0, m = 0;
    std::unordered_map<int, tEdge> edges;
    std::unordered_map<std::tuple<int, time_t, inout>, std::unordered_set<int>, tuple_hash> in, out;
    std::unordered_set<std::tuple<int, time_t, inout>, tuple_hash> dis1, dis2;
    std::queue<std::tuple<int, time_t, inout>> q1, q2;
    std::unordered_map<int, std::set<time_t>> intimes, outtimes;
    int bisearch(int source, int target, time_t start, time_t end);
    int search1(int source, int target, time_t start, time_t end);
};

void help1(std::string filename);
void help2(std::string filename);

#endif //UNTITLED_BISEARCH_H
